<?php

namespace Core\Common\Base\Db;

/**
 * Description of DataAccessor
 *
 * @author baiyang@ibantang.com
 */
class DataAccessor
{
    // connection 名字，是一个字符串
    protected $connection = '';
    protected $table = '';
    protected $primaryKey = 'id';

    protected $where = [];
    protected $option = [];

    public function __construct($connection, $table, $primaryKey)
    {
        $this->connection = $connection;
        $this->table = $table;
        $this->primaryKey = $primaryKey;
    }

    public function reset()
    {
        $this->where = [];
        $this->option = [];
    }

    public function where($k, $op = null, $v = null)
    {
        if (is_array($k)) {//数组传递多个条件
            $this->where = $k + $this->where;
        } elseif (!is_null($op) && is_null($v)) {//单个条件
            $this->where[$k] = $op;
        } elseif (!is_null($op) && !is_null($v)) {//带操作符
            if (strtoupper($op) == 'IN') {
                $this->where[$k] = $v;
            } else {
                $this->where[] = "`$k`{$op}{$v}";
            }
        }
        return $this;
    }

    public function limit($num, $offset = null)
    {
        $this->option['limit'] = (int)$num;
        if (!is_null($offset) && (is_int($offset) || ctype_digit($offset))) {
            $this->option['offset'] = $offset;
        }
        return $this;
    }

    public function orderBy($field, $order = 'ASC')
    {
        $this->option['orderby'][] = "`$field` $order";
        return $this;
    }

    public function groupBy(...$fields)
    {
        $this->option['groupby'] = $fields;
        return $this;
    }

    public function having($exp, $op, $value)
    {
        $this->option['having'][] = "{$exp}{$op}{$value}";
        return $this;
    }

    public function find($id, $fields = [])
    {
        $where = [];
        if (is_array($this->primaryKey)) {
            foreach ($this->primaryKey as $k) {
                if (isset($id[$k])) {
                    $where[$k] = $id[$k];
                }
            }
        } else {
            $where[$this->primaryKey] = $id;
        }
        if (empty($where)) {
            return false;
        }
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::getOne($fields, $this->where, $this->option);
    }

    public function first()
    {
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::getOne([], $this->where, $this->option);
    }

    public function get($fields = [])
    {
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::getData($fields, $this->where, $this->option);
    }

    public function pluck(mixed $key)
    {
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::pluck([], $this->where, $key);
    }

    /**
     * 根据查询条件获取key-value结构, 相同的key会覆盖
     * @param mixed $keyField 返回数据结构的key字段, 可以是数组（多维结构）
     * @param mixed $valueField 返回数据结构的value字段
     * @return type
     */
    public function kv(mixed $keyField, mixed $valueField)
    {
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::getKv($this->where, $keyField, $valueField, $this->option);
    }

    /**
     * 根据查询条件获取key-value结构, 相同的key不覆盖, 写到一个数组里
     * @param mixed $keyField 返回数据结构的key字段, 可以是数组（多维结构）
     * @param mixed $valueField 返回数据结构的value字段
     * @return type
     */
    public function map(mixed $keyField, mixed $valueField)
    {
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::getMap($this->where, $keyField, $valueField, $this->option);
    }

    public function union($fields = [])
    {
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::union($this->where, $this->option, $fields);
    }

    /**
     * 保存数据, 不存在则添加，存在可以忽略，可以覆盖（批量更新）
     * @param mixed $vals 要添加的数据
     * @param mixed $update 如果存在相同主键或唯一键数据，要更新的字段列表；不写，就忽略
     * @param mixed $unEscapeFields 不转义的字段
    * @return type
     */
    public function save($vals, $update = [], $unEscapeFields = [])
    {
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::addDuplicateData($vals, $update, $unEscapeFields);
    }

    public function update($vals)
    {
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::updateData($vals, $this->where);
    }

    public function delete()
    {
        $instance = Database::getStaticInstance($this->connection, $this->table);
        return $instance::deleteData($this->where);
    }
}
